#ifndef ModelMatch_h
#define ModelMatch_h

#include "CourtModel.h"
#include "Frame.h"
#include "Line.h"
#include "Intersection.h"

class ModelMatch
{
	Frame _realWorld;
	CourtModel _model;

	std::vector<Line> _rwHPair;
	std::vector<Line> _rwVPair;

	std::vector<Line> _mHPair;
	std::vector<Line> _mVPair;

	cv::Mat _H;
	double _f;
	double _B;

	double _score;

	cv::Mat _lineMask;

public:

	std::vector<Intersection> _mIntSecs;
	std::vector<Intersection> _rwIntSecs;

	ModelMatch(Frame, CourtModel);
	ModelMatch(void);
	~ModelMatch(void);

	void ModelMatch::updateFrame(Frame newFrame);

	double fitModelWithRandomTries();
	double fitModelWithRandomTries(int);
	double fitModelExaustive();
	double fitModelExaustive(Line, Line, Line, Line);
	double fitModelExaustiveWithRandomTries(int);

	
	double fitModelAbsolute(cv::Mat&, Line, Line, Line, Line);
	double fitModelAbsolute(cv::Mat&, Line, Line, bool);

	double fastModelExaustiveFit(cv::Mat&);
	double modelExaustiveFit(cv::Mat&, std::vector<Line>, std::vector<Line>, bool);

	double pointModelExaustiveFit(cv::Mat& H);
	double computeHomographyWithIntersections(std::vector<cv::Point>, cv::Mat&);
	double scoreMappedModelLines(std::vector<Line>,std::vector<Line>);
	double scoreMappedModelLines2(std::vector<Line>,std::vector<Line>);
	bool goodMatch(int, int);

	std::vector<Line> chooseLinePair(std::vector<Line>);
	std::vector<cv::Point> computeIntersections(Line, Line, Line, Line);
	std::vector<cv::Point> computeIntersections(Line, Line, Line, Line, std::vector<Intersection>&);

	cv::Mat computeHomography(std::vector<cv::Point>, std::vector<cv::Point>);
	cv::Mat buildPPrime(cv::Point, cv::Point, cv::Point, cv::Point);
	cv::Mat ModelMatch::buildA(cv::Point, cv::Point, cv::Point, cv::Point, 
		cv::Point, cv::Point, cv::Point, cv::Point);
	double getF(cv::Mat);
	double getB(cv::Mat);

	cv::Mat getHomography();

	double scoreHomographySymmetricL2(std::vector<cv::Point>, std::vector<cv::Point>, cv::Mat);
	double scoreHomography(std::vector<cv::Point>, std::vector<cv::Point>, cv::Mat);
	double scoreHomography(std::vector<Intersection>, std::vector<Intersection>, cv::Mat);
	double scoreHomographyL2(std::vector<cv::Point2f> rwPoints, std::vector<cv::Point2f> modelPts, cv::Mat H);
	double scoreHomographyL2(std::vector<cv::Point> rwPoints, std::vector<cv::Point> modelPts, cv::Mat H);
	double scoreHomographyL2HorizontalLines(cv::Mat H, bool);
	double scoreHomographyL2VerticalLines(cv::Mat H, bool);
	//double horizontalResidualAreaScore(cv::Mat H);
	//double verticalResidualAreaScore(cv::Mat H);

	double minDist(std::vector<cv::Point>, cv::Point);
	double minDist(std::vector<Intersection>, cv::Point);
	double getScore();
	double scoreHomographyWithLineFilling(cv::Mat, cv::Mat, std::vector<Line>);
	void translateLine(cv::Mat, Line&, Line);
	double getBlackPixelScore(cv::Mat);
	bool withinFrame(Frame, std::vector<Line>, cv::Mat);
	bool withinBounds(std::vector<Line>, std::vector<Line>, cv::Mat);
	bool withinBoundsRect(std::vector<cv::Point>, Line);
	bool withinBoundsTriangle(cv::Point, cv::Point, cv::Point, cv::Point);
	bool sameSide(cv::Point,cv::Point,cv::Point,cv::Point);

	std::vector<cv::Point> translateMtoRW(cv::Mat, std::vector<cv::Point>);
	std::vector<cv::Point> translateRWtoM(cv::Mat, std::vector<cv::Point>);
	cv::Point translatePtoPPrime(cv::Point, cv::Mat);
	cv::Point translatePPrimetoP(cv::Point, cv::Mat);

	void drawModelInFrame(cv::Mat, cv::Mat, std::vector<Line>&, std::vector<Line>&);
	bool checkProjectedLines(cv::Mat);
};

#endif